

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="https://img.mkerosene.cn/touxiang.jpg">
  <link rel="icon" href="https://img.mkerosene.cn/touxiang.jpg">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
    <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="Kerosene W">
  <meta name="keywords" content="">
  
    <meta name="description" content="总览[原文档地址][https:&#x2F;&#x2F;missing-semester-cn.github.io&#x2F;] [视频链接][https:&#x2F;&#x2F;www.bilibili.com&#x2F;video&#x2F;BV1x7411H7wa]  1. 课程概览与 shell 2.Shell 工具和脚本 3. 编辑器 (Vim) 4. 数据整理 5. 命令行环境 6.版本控制(Git) 7.调试及性能分析 8.元编程 9.大杂烩   Th">
<meta property="og:type" content="article">
<meta property="og:title" content="计算机教育中缺失的一课(一)">
<meta property="og:url" content="http://example.com/2021/10/26/%E8%AE%A1%E7%AE%97%E6%9C%BA%E6%95%99%E8%82%B2%E4%B8%AD%E7%BC%BA%E5%A4%B1%E7%9A%84%E4%B8%80%E8%AF%BE(%E4%B8%80)/index.html">
<meta property="og:site_name" content="追求源于热爱">
<meta property="og:description" content="总览[原文档地址][https:&#x2F;&#x2F;missing-semester-cn.github.io&#x2F;] [视频链接][https:&#x2F;&#x2F;www.bilibili.com&#x2F;video&#x2F;BV1x7411H7wa]  1. 课程概览与 shell 2.Shell 工具和脚本 3. 编辑器 (Vim) 4. 数据整理 5. 命令行环境 6.版本控制(Git) 7.调试及性能分析 8.元编程 9.大杂烩   Th">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2021-10-26T12:52:11.000Z">
<meta property="article:modified_time" content="2021-10-28T12:09:05.775Z">
<meta property="article:author" content="Kerosene W">
<meta property="article:tag" content="Linux">
<meta property="article:tag" content="missing-semester">
<meta name="twitter:card" content="summary_large_image">
  
  
  <title>计算机教育中缺失的一课(一) - 追求源于热爱</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@10/styles/github-gist.min.css" />
    
  

  
    <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.css" />
  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    var CONFIG = {"hostname":"example.com","root":"/","version":"1.8.13","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":"❡"},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"copy_btn":true,"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"https://img.mkerosene.cn/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":"FI1uAFAYz0Q3MPDiORqd0JAN-gzGzoHsz","app_key":"EhKAjMe3bmq0WLTSgktGg2OC","server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/local-search.xml"};
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
</head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>mKerosene</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/links/">
                <i class="iconfont icon-link-fill"></i>
                友链
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              &nbsp;<i class="iconfont icon-search"></i>&nbsp;
            </a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner" id="banner" parallax=true
         style="background: url('https://img.mkerosene.cn/default.png') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="page-header text-center fade-in-up">
            <span class="h2" id="subtitle" title="计算机教育中缺失的一课(一)">
              
            </span>

            
              <div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2021-10-26 20:52" pubdate>
        2021年10月26日 晚上
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      5.7k 字
    </span>
  

  
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      18 分钟
    </span>
  

  
  
    
      <!-- LeanCloud 统计文章PV -->
      <span id="leancloud-page-views-container" class="post-meta" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="leancloud-page-views"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">计算机教育中缺失的一课(一)</h1>
            
              <p class="note note-info">
                
                  本文最后更新于：1 年前
                
              </p>
            
            <div class="markdown-body">
              <h1 id="总览"><a href="#总览" class="headerlink" title="总览"></a>总览</h1><p>[原文档地址][<a target="_blank" rel="noopener" href="https://missing-semester-cn.github.io/]">https://missing-semester-cn.github.io/]</a></p>
<p>[视频链接][<a target="_blank" rel="noopener" href="https://www.bilibili.com/video/BV1x7411H7wa]">https://www.bilibili.com/video/BV1x7411H7wa]</a></p>
<ul>
<li><strong>1.</strong> <a target="_blank" rel="noopener" href="https://missing-semester-cn.github.io/2020/course-shell/">课程概览与 shell</a></li>
<li><strong>2.</strong><a target="_blank" rel="noopener" href="https://missing-semester-cn.github.io/2020/shell-tools/">Shell 工具和脚本</a></li>
<li><strong>3.</strong> <a target="_blank" rel="noopener" href="https://missing-semester-cn.github.io/2020/editors/">编辑器 (Vim)</a></li>
<li><strong>4.</strong> <a target="_blank" rel="noopener" href="https://missing-semester-cn.github.io/2020/data-wrangling/">数据整理</a></li>
<li><strong>5.</strong> <a target="_blank" rel="noopener" href="https://missing-semester-cn.github.io/2020/command-line/">命令行环境</a></li>
<li><strong>6.</strong><a target="_blank" rel="noopener" href="https://missing-semester-cn.github.io/2020/version-control/">版本控制(Git)</a></li>
<li><strong>7.</strong><a target="_blank" rel="noopener" href="https://missing-semester-cn.github.io/2020/debugging-profiling/">调试及性能分析</a></li>
<li><strong>8.</strong><a target="_blank" rel="noopener" href="https://missing-semester-cn.github.io/2020/metaprogramming/">元编程</a></li>
<li><strong>9.</strong><a target="_blank" rel="noopener" href="https://missing-semester-cn.github.io/2020/potpourri/">大杂烩</a></li>
</ul>
<hr>
<h1 id="The-Shell"><a href="#The-Shell" class="headerlink" title="The Shell"></a>The Shell</h1><h2 id="shell-是什么？"><a href="#shell-是什么？" class="headerlink" title="shell 是什么？"></a>shell 是什么？</h2><p>​        如今的计算机有着多种多样的交互接口让我们可以进行指令的的输入，从炫酷的图像用户界面（GUI），语音输入甚至是 AR/VR 都已经无处不在。 这些交互接口可以覆盖 80% 的使用场景，但是它们也从根本上限制了您的操作方式——你不能点击一个不存在的按钮或者是用语音输入一个还没有被录入的指令。 为了充分利用计算机的能力，我们不得不回到最根本的方式，使用文字接口：Shell</p>
<p>​        几乎所有您能够接触到的平台都支持某种形式的 shell，有些甚至还提供了多种 shell 供您选择。虽然它们之间有些细节上的差异，但是其核心功能都是一样的：它允许你执行程序，输入并获取某种半结构化的输出。</p>
<p>​        本节课我们会使用 Bourne Again SHell, 简称 “bash” 。 这是被最广泛使用的一种 shell，它的语法和其他的 shell 都是类似的。打开shell <em>提示符</em>（您输入指令的地方），您首先需要打开 <em>终端</em> 。您的设备通常都已经内置了终端，或者您也可以安装一个，非常简单。</p>
<h2 id="使用-shell"><a href="#使用-shell" class="headerlink" title="使用 shell"></a>使用 shell</h2><p>当您打开终端时，您会看到一个提示符，它看起来一般是这个样子的：</p>
<figure class="highlight avrasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs avrasm"><span class="hljs-symbol">missing:</span>~$ <br></code></pre></td></tr></table></figure>

<p>​        这是 shell 最主要的文本接口。它告诉你，你的主机名是 <code>missing</code> 并且您当前的工作目录（”current working directory”）或者说您当前所在的位置是 <code>~</code> (表示 “home”)。 <code>$</code> 符号表示您现在的身份不是 root 用户（稍后会介绍）。在这个提示符中，您可以输入 <em>命令</em> ，命令最终会被 shell 解析。最简单的命令是执行一个程序：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">missing</span>:~$ date<br><span class="hljs-attribute">Fri</span> <span class="hljs-number">10</span> Jan <span class="hljs-number">2020</span> <span class="hljs-number">11</span>:<span class="hljs-number">49</span>:<span class="hljs-number">31</span> AM EST<br><span class="hljs-attribute">missing</span>:~$ <br></code></pre></td></tr></table></figure>

<p>​        这里，我们执行了 <code>date</code> 这个程序，不出意料地，它打印出了当前的日前和时间。然后，shell 等待我们输入其他命令。我们可以在执行命令的同时向程序传递 <em>参数</em> ：</p>
<figure class="highlight vim"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs vim">missin<span class="hljs-variable">g:</span>~$ <span class="hljs-keyword">echo</span> hello<br>hello<br></code></pre></td></tr></table></figure>

<p>上例中，我们让 shell 执行 <code>echo</code> ，同时指定参数 <code>hello</code>。<code>echo</code> 程序将该参数打印出来。 shell 基于空格分割命令并进行解析，然后执行第一个单词代表的程序，并将后续的单词作为程序可以访问的参数。如果您希望传递的参数中包含空格（例如一个名为 My Photos 的文件夹），您要么用使用单引号，双引号将其包裹起来，要么使用转义符号 <code>\</code> 进行处理（<code>My\ Photos</code>）。</p>
<p>​        但是，shell 是如何知道去哪里寻找 <code>date</code> 或 <code>echo</code> 的呢？其实，类似于 Python 或 Ruby，shell 是一个编程环境，所以它具备变量、条件、循环和函数（下一课进行讲解）。当你在 shell 中执行命令时，您实际上是在执行一段 shell 可以解释执行的简短代码。如果你要求 shell 执行某个指令，但是该指令并不是 shell 所了解的编程关键字，那么它会去咨询 <em>环境变量</em> <code>$PATH</code>，它会列出当 shell 接到某条指令时，进行程序搜索的路径：</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs awk">missing:~$ echo <span class="hljs-variable">$PATH</span><br><span class="hljs-regexp">/usr/</span>local<span class="hljs-regexp">/sbin:/u</span>sr<span class="hljs-regexp">/local/</span>bin:<span class="hljs-regexp">/usr/</span>sbin:<span class="hljs-regexp">/usr/</span>bin:<span class="hljs-regexp">/sbin:/</span>bin<br>missing:~$ which echo<br><span class="hljs-regexp">/bin/</span>echo<br>missing:~$ <span class="hljs-regexp">/bin/</span>echo <span class="hljs-variable">$PATH</span><br><span class="hljs-regexp">/usr/</span>local<span class="hljs-regexp">/sbin:/u</span>sr<span class="hljs-regexp">/local/</span>bin:<span class="hljs-regexp">/usr/</span>sbin:<span class="hljs-regexp">/usr/</span>bin:<span class="hljs-regexp">/sbin:/</span>bin<br></code></pre></td></tr></table></figure>

<p>​        当我们执行 <code>echo</code> 命令时，shell 了解到需要执行 <code>echo</code> 这个程序，随后它便会在 <code>$PATH</code> 中搜索由 <code>:</code> 所分割的一系列目录，基于名字搜索该程序。当找到该程序时便执行（假定该文件是 <em>可执行程序</em>，后续课程将详细讲解）。确定某个程序名代表的是哪个具体的程序，可以使用 <code>which</code> 程序。我们也可以绕过 <code>$PATH</code>，通过直接指定需要执行的程序的路径来执行该程序</p>
<h2 id="在shell中导航"><a href="#在shell中导航" class="headerlink" title="在shell中导航"></a>在shell中导航</h2><p>​        shell 中的路径是一组被分割的目录，在 Linux 和 macOS 上使用 <code>/</code> 分割，而在Windows上是 <code>\</code>。路径 <code>/</code> 代表的是系统的根目录，所有的文件夹都包括在这个路径之下，在Windows上每个盘都有一个根目录（例如： <code>C:\</code>）。 我们假设您在学习本课程时使用的是 Linux 文件系统。如果某个路径以 <code>/</code> 开头，那么它是一个 <em>绝对路径</em>，其他的都是 <em>相对路径</em> 。相对路径是指相对于当前工作目录的路径，当前工作目录可以使用 <code>pwd</code> 命令来获取。此外，切换目录需要使用 <code>cd</code> 命令。在路径中，<code>.</code> 表示的是当前目录，而 <code>..</code> 表示上级目录：</p>
<figure class="highlight jboss-cli"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs jboss-cli">missing:~$ <span class="hljs-keyword">pwd</span><br><span class="hljs-string">/home/missing</span><br>missing:~$ <span class="hljs-keyword">cd</span> <span class="hljs-string">/home</span><br>missing:<span class="hljs-string">/home</span>$ <span class="hljs-keyword">pwd</span><br><span class="hljs-string">/home</span><br>missing:<span class="hljs-string">/home</span>$ <span class="hljs-keyword">cd</span> <span class="hljs-string">..</span><br>missing:/$ <span class="hljs-keyword">pwd</span><br>/<br>missing:/$ <span class="hljs-keyword">cd</span> <span class="hljs-string">./home</span><br>missing:<span class="hljs-string">/home</span>$ <span class="hljs-keyword">pwd</span><br><span class="hljs-string">/home</span><br>missing:<span class="hljs-string">/home</span>$ <span class="hljs-keyword">cd</span> missing<br>missing:~$ <span class="hljs-keyword">pwd</span><br><span class="hljs-string">/home/missing</span><br>missing:~$ <span class="hljs-string">../../bin/echo</span> hello<br>hello<br></code></pre></td></tr></table></figure>

<p>​        注意，shell 会实时显示当前的路径信息。您可以通过配置 shell 提示符来显示各种有用的信息，这一内容我们会在后面的课程中进行讨论。</p>
<p>​        一般来说，当我们运行一个程序时，如果我们没有指定路径，则该程序会在当前目录下执行。例如，我们常常会搜索文件，并在需要时创建文件。</p>
<p>为了查看指定目录下包含哪些文件，我们使用 <code>ls</code> 命令：</p>
<figure class="highlight jboss-cli"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs jboss-cli">missing:~$ <span class="hljs-keyword">ls</span><br>missing:~$ <span class="hljs-keyword">cd</span> <span class="hljs-string">..</span><br>missing:<span class="hljs-string">/home</span>$ <span class="hljs-keyword">ls</span><br>missing<br>missing:<span class="hljs-string">/home</span>$ <span class="hljs-keyword">cd</span> <span class="hljs-string">..</span><br>missing:/$ <span class="hljs-keyword">ls</span><br>bin<br>boot<br>dev<br>etc<br>home<br><span class="hljs-string">...</span><br></code></pre></td></tr></table></figure>

<p>​        除非我们利用第一个参数指定目录，否则 <code>ls</code> 会打印当前目录下的文件。大多数的命令接受标记和选项（带有值的标记），它们以 <code>-</code> 开头，并可以改变程序的行为。通常，在执行程序时使用 <code>-h</code> 或 <code>--help</code> 标记可以打印帮助信息，以便了解有哪些可用的标记或选项。例如，<code>ls --help</code> 的输出如下：</p>
<figure class="highlight sas"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs sas">  -l                         use a long listing <span class="hljs-meta">format</span><br><span class="hljs-meta">missing</span>:~$ ls -l /home<br>drwxr-xr-<span class="hljs-meta">x</span> 1 <span class="hljs-meta">missing</span>  users  4096 Jun 15  2019 <span class="hljs-meta">missing</span><br></code></pre></td></tr></table></figure>

<p>​        这个参数可以打印出更加详细地列出目录下文件或文件夹的信息。首先，本行第一个字符 <code>d</code> 表示 <code>missing</code> 是一个目录。然后接下来的九个字符，每三个字符构成一组。 （<code>rwx</code>）. 它们分别代表了文件所有者（<code>missing</code>），用户组（<code>users</code>） 以及其他所有人具有的权限。其中 <code>-</code> 表示该用户不具备相应的权限。从上面的信息来看，只有文件所有者可以修改（<code>w</code>），<code>missing</code> 文件夹 （例如，添加或删除文件夹中的文件）。为了进入某个文件夹，用户需要具备该文件夹以及其父文件夹的“搜索”权限（以“可执行”：<code>x</code>）权限表示。为了列出它的包含的内容，用户必须对该文件夹具备读权限（<code>r</code>）。对于文件来说，权限的意义也是类似的。注意，<code>/bin</code> 目录下的程序在最后一组，即表示所有人的用户组中，均包含 <code>x</code> 权限，也就是说任何人都可以执行这些程序。</p>
<p>​        在这个阶段，还有几个趁手的命令是您需要掌握的，例如 <code>mv</code>（用于重命名或移动文件）、 <code>cp</code>（拷贝文件）以及 <code>mkdir</code>（新建文件夹）。</p>
<p>​        如果您想要知道关于程序参数、输入输出的信息，亦或是想要了解它们的工作方式，请试试 <code>man</code> 这个程序。它会接受一个程序名作为参数，然后将它的文档（用户手册）展现给您。注意，使用 <code>q</code> 可以退出该程序。</p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs powershell">missing:~<span class="hljs-variable">$</span> <span class="hljs-built_in">man</span> <span class="hljs-built_in">ls</span><br></code></pre></td></tr></table></figure>

<h2 id="在程序间创建连接"><a href="#在程序间创建连接" class="headerlink" title="在程序间创建连接"></a>在程序间创建连接</h2><p>​        在 shell 中，程序有两个主要的“流”：它们的输入流和输出流。 当程序尝试读取信息时，它们会从输入流中进行读取，当程序打印信息时，它们会将信息输出到输出流中。 通常，一个程序的输入输出流都是您的终端。也就是，您的键盘作为输入，显示器作为输出。 但是，我们也可以重定向这些流！</p>
<p>最简单的重定向是 <code>&lt; file</code> 和 <code>&gt; file</code>。这两个命令可以将程序的输入输出流分别重定向到文件：</p>
<figure class="highlight vim"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs vim">missin<span class="hljs-variable">g:</span>~$ <span class="hljs-keyword">echo</span> hello &gt; hello.txt<br>missin<span class="hljs-variable">g:</span>~$ <span class="hljs-keyword">cat</span> hello.txt<br>hello<br>missin<span class="hljs-variable">g:</span>~$ <span class="hljs-keyword">cat</span> &lt; hello.txt<br>hello<br>missin<span class="hljs-variable">g:</span>~$ <span class="hljs-keyword">cat</span> &lt; hello.txt &gt; hello2.txt<br>missin<span class="hljs-variable">g:</span>~$ <span class="hljs-keyword">cat</span> hello2.txt<br>hello<br></code></pre></td></tr></table></figure>

<p>​        您还可以使用 <code>&gt;&gt;</code> 来向一个文件追加内容。使用管道（ <em>pipes</em> ），我们能够更好的利用文件重定向。 <code>|</code> 操作符允许我们将一个程序的输出和另外一个程序的输入连接起来：</p>
<figure class="highlight vim"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs vim">missin<span class="hljs-variable">g:</span>~$ <span class="hljs-keyword">ls</span> -<span class="hljs-keyword">l</span> / | tail -n1<br>drwxr-xr-<span class="hljs-keyword">x</span> <span class="hljs-number">1</span> root  root  <span class="hljs-number">4096</span> Jun <span class="hljs-number">20</span>  <span class="hljs-number">2019</span> var<br>missin<span class="hljs-variable">g:</span>~$ curl --head --<span class="hljs-keyword">silent</span> google.<span class="hljs-keyword">com</span> | <span class="hljs-keyword">grep</span> --ignore-case content-length | cut --delimiter=<span class="hljs-string">&#x27; &#x27;</span> -f2<br><span class="hljs-number">219</span><br></code></pre></td></tr></table></figure>

<p>我们会在数据清理一章中更加详细的探讨如何更好的利用管道。</p>
<h2 id="一个功能全面又强大的工具"><a href="#一个功能全面又强大的工具" class="headerlink" title="一个功能全面又强大的工具"></a>一个功能全面又强大的工具</h2><p>​        对于大多数的类 Unix 系统，有一类用户是非常特殊的，那就是：根用户（root user）。 您应该已经注意到了，在上面的输出结果中，根用户几乎不受任何限制，他可以创建、读取、更新和删除系统中的任何文件。 通常在我们并不会以根用户的身份直接登录系统，因为这样可能会因为某些错误的操作而破坏系统。 取而代之的是我们会在需要的时候使用 <code>sudo</code> 命令。顾名思义，它的作用是让您可以以 su（super user 或 root 的简写）的身份执行一些操作。 当您遇到拒绝访问（permission denied）的错误时，通常是因为此时您必须是根用户才能操作。然而，请再次确认您是真的要执行此操作。</p>
<p>​        有一件事情是您必须作为根用户才能做的，那就是向 <code>sysfs</code> 文件写入内容。系统被挂载在 <code>/sys</code> 下，<code>sysfs</code> 文件则暴露了一些内核（kernel）参数。 因此，您不需要借助任何专用的工具，就可以轻松地在运行期间配置系统内核。<strong>注意 Windows 和 macOS 没有这个文件</strong></p>
<p>例如，您笔记本电脑的屏幕亮度写在 <code>brightness</code> 文件中，它位于</p>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs gradle"><span class="hljs-regexp">/sys/</span><span class="hljs-keyword">class</span>/backlight<br></code></pre></td></tr></table></figure>

<p>通过将数值写入该文件，我们可以改变屏幕的亮度。现在，蹦到您脑袋里的第一个想法可能是：</p>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs gradle">$ sudo <span class="hljs-keyword">find</span> -L <span class="hljs-regexp">/sys/</span><span class="hljs-keyword">class</span>/backlight -maxdepth <span class="hljs-number">2</span> -name <span class="hljs-string">&#x27;*brightness*&#x27;</span><br><span class="hljs-regexp">/sys/</span><span class="hljs-keyword">class</span><span class="hljs-regexp">/backlight/</span>thinkpad_screen/brightness<br>$ cd <span class="hljs-regexp">/sys/</span><span class="hljs-keyword">class</span><span class="hljs-regexp">/backlight/</span>thinkpad_screen<br>$ sudo echo <span class="hljs-number">3</span> &gt; brightness<br>An error occurred <span class="hljs-keyword">while</span> redirecting <span class="hljs-keyword">file</span> <span class="hljs-string">&#x27;brightness&#x27;</span><br>open: Permission denied<br></code></pre></td></tr></table></figure>

<p>​        出乎意料的是，我们还是得到了一个错误信息。毕竟，我们已经使用了 <code>sudo</code> 命令！关于 shell，有件事我们必须要知道。<code>|</code>、<code>&gt;</code>、和 <code>&lt;</code> 是通过 shell 执行的，而不是被各个程序单独执行。 <code>echo</code> 等程序并不知道 <code>|</code> 的存在，它们只知道从自己的输入输出流中进行读写。 对于上面这种情况， <em>shell</em> (权限为您的当前用户) 在设置 <code>sudo echo</code> 前尝试打开 brightness 文件并写入，但是系统拒绝了 shell 的操作因为此时 shell 不是根用户。</p>
<p>明白这一点后，我们可以这样操作：</p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs powershell"><span class="hljs-variable">$</span> <span class="hljs-built_in">echo</span> <span class="hljs-number">3</span> | sudo <span class="hljs-built_in">tee</span> brightness<br></code></pre></td></tr></table></figure>

<p>​        因为打开 <code>/sys</code> 文件的是 <code>tee</code> 这个程序，并且该程序以 <code>root</code> 权限在运行，因此操作可以进行。 这样您就可以在 <code>/sys</code> 中愉快地玩耍了，例如修改系统中各种LED的状态（路径可能会有所不同）：</p>
<figure class="highlight angelscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs angelscript">$ echo <span class="hljs-number">1</span> | sudo tee /sys/<span class="hljs-keyword">class</span>/<span class="hljs-symbol">leds</span>/<span class="hljs-symbol">input6::<span class="hljs-symbol">scrolllock</span></span>/<span class="hljs-symbol">brightness</span><br></code></pre></td></tr></table></figure>

<h1 id="笔记"><a href="#笔记" class="headerlink" title="笔记"></a>笔记</h1><ol>
<li><code>cd</code>命令，参数<code>-</code>返回上一目录，<code>~</code>返回当前账户目录</li>
<li><code>&#39;</code>引起的内容为原原字符串，<code>“</code>引起的内容则表示先执行引起内容并返回值，<code>#</code>表注释</li>
</ol>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs shell"><span class="hljs-meta">$</span><span class="bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">&#x27;echo $PATH&#x27;</span> &gt; path.txt</span><br><span class="hljs-meta">$</span><span class="bash">cat path.txt</span><br><span class="hljs-meta">#</span><span class="bash"> 输出<span class="hljs-built_in">echo</span> <span class="hljs-variable">$PATH</span></span><br><span class="hljs-meta">$</span><span class="bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">&quot;echo <span class="hljs-variable">$PATH</span>&quot;</span> &gt; path.txt</span><br><span class="hljs-meta">$</span><span class="bash">cat path.txt</span><br><span class="hljs-meta">#</span><span class="bash"> 输出<span class="hljs-built_in">echo</span> /usr/<span class="hljs-built_in">local</span>/sbin:/usr/<span class="hljs-built_in">local</span>/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/<span class="hljs-built_in">local</span>/games:/usr/games</span><br></code></pre></td></tr></table></figure>

<ol start="3">
<li><p>使用 <code>chmod</code> 命令改变权限：<code>drwxr-xr-x 1 root  root  </code></p>
<ul>
<li> 第一个位置<code>d</code>表示文件目录，若<code>-</code>表示文件</li>
<li>其后每三个一组，依次表示文件所有者（Owner）、用户组（Group）、其它用户（Other Users），每个位置依次表示读、写和执行权限</li>
<li>改变权限时</li>
</ul>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs shell"><span class="hljs-meta">#</span><span class="bash"> 符号模式：ugo表示三级用户组，+-=改变权限</span><br><span class="hljs-meta">$</span><span class="bash">chmod a=rwx file 或 chmod ugo=rwx file</span><br><span class="hljs-meta">#</span><span class="bash"> 八进制语法：对应二进制数，增加权限为1，去除权限为0</span><br><span class="hljs-meta">$</span><span class="bash">chmod 777 filename		<span class="hljs-comment"># 权限全开</span></span><br></code></pre></td></tr></table></figure></li>
<li><p><code>tee</code>命令用于读取标准输入的数据，并将其内容输出成文件。</p>
</li>
<li><p>命令文档：<code>man 命令</code></p>
</li>
<li><p><code>&gt;</code>流输入，<code>&gt;&gt;</code>追加</p>
</li>
</ol>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/note/">note</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/Linux/">Linux</a>
                    
                      <a class="hover-with-bg" href="/tags/missing-semester/">missing-semester</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">
                  
                    本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！
                  
                </p>
              
              
                <div class="post-prevnext">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2021/10/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E6%95%99%E8%82%B2%E4%B8%AD%E7%BC%BA%E5%A4%B1%E7%9A%84%E4%B8%80%E8%AF%BE(%E4%BA%8C)/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">计算机教育中缺失的一课(二)</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2021/09/10/WinRAR%E7%9A%84%E5%91%BD%E4%BB%A4%E8%A1%8C%E6%A8%A1%E5%BC%8F%E7%94%A8%E6%B3%95%E4%BB%8B%E7%BB%8D-%E8%BD%AC/">
                        <span class="hidden-mobile">WinRAR的命令行模式用法介绍(转)</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
              <!-- Comments -->
              <article class="comments" id="comments" lazyload>
                
                  
                
                
  <div id="twikoo"></div>
  <script type="text/javascript">
    Fluid.utils.loadComments('#comments', function() {
      Fluid.utils.createScript('https://cdn.jsdelivr.net/npm/twikoo@1/dist/twikoo.all.min.js', function() {
        var options = Object.assign(
          {"envId":"blog-3gentarg3e6a1b5e","region":"ap-shanghai","path":"window.location.pathname"},
          {
            el: '#twikoo',
            path: 'window.location.pathname',
            onCommentLoaded: function() {
              Fluid.plugins.initFancyBox('#twikoo .tk-content img:not(.tk-owo-emotion)');
            }
          }
        )
        twikoo.init(options)
      });
    });
  </script>
  <noscript>Please enable JavaScript to view the comments</noscript>


              </article>
            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
    

    
  </main>

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <div class="copyright">&copy;2020 - 2021 By Kerosene.W</div> <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
  </div>
  
  <div class="statistics">
    
    

    
      
        <!-- LeanCloud 统计PV -->
        <span id="leancloud-site-pv-container" style="display: none">
            总访问量 
            <span id="leancloud-site-pv"></span>
             次
          </span>
      
      
        <!-- LeanCloud 统计UV -->
        <span id="leancloud-site-uv-container" style="display: none">
            总访客数 
            <span id="leancloud-site-uv"></span>
             人
          </span>
      

    
  </div>


  

  
</footer>


  <!-- SCRIPTS -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>

<!-- Plugins -->


  <script  src="/js/local-search.js" ></script>



  
    <script  src="/js/img-lazyload.js" ></script>
  



  



  
    <script  src="https://cdn.jsdelivr.net/npm/tocbot@4/dist/tocbot.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/anchor-js@4/anchor.min.js" ></script>
  
  
    <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js" ></script>
  




  <script defer src="/js/leancloud.js" ></script>



  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var title = document.getElementById('subtitle').title;
      
        typing(title);
      
    })(window, document);
  </script>












  

  

  

  

  

  





<!-- 主题的启动项 保持在最底部 -->
<script  src="/js/boot.js" ></script>


</body>
</html>
